package com.example.opengldemo.vertex_shader_more.file_version_1;


import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.view.MotionEvent;

import com.example.opengldemo.R;
import com.example.opengldemo.util.MatrixState;

import static com.example.opengldemo.vertex_shader_more.file_version_1.ParticleDataConstant.COUNT;
import static com.example.opengldemo.vertex_shader_more.file_version_1.ParticleDataConstant.CURR_INDEX;
import static com.example.opengldemo.vertex_shader_more.file_version_1.ParticleDataConstant.RADIS;
 class MySurfaceView extends GLSurfaceView {
    public static float WIDTH;
    public static float HEIGHT;

    private SceneRenderer mRenderer;

    List<ParticleSystem> fps = new ArrayList<ParticleSystem>();
    ParticleForDraw[] fpfd;

    static float direction = 0;
    static float cx = 0;
    static float cy = 18;
    static float cz = 20;
    static float tx = 0;
    static float ty = 5;
    static float tz = 0;
    static float ux = -cx;
    static float uy = Math.abs((cx * tx + cz * tz - cx * cx - cz * cz) / (ty - cy));
    static float uz = -cz;
    static final float DEGREE_SPAN = (float) (3.0 / 180.0f * Math.PI);

    float Offset = 20;
    float preX;
    float preY;
    float x;
    float y;

    int textureIdFire;
    int textureIdbrazier;
    int count;

    boolean flag = true;

    public MySurfaceView(Context context) {
        super(context);
        this.setEGLContextClientVersion(3);
        mRenderer = new SceneRenderer();
        setRenderer(mRenderer);
        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        x = event.getX();
        y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                flag = true;
                new Thread() {
                    @Override
                    public void run() {
                        while (flag) {
                            if (x > WIDTH / 4 && x < 3 * WIDTH / 4 && y > 0 && y < HEIGHT / 2) {
                                if (Math.abs(Offset - 0.5f) > 25 || Math.abs(Offset - 0.5f) < 15) {
                                    return;
                                }
                                Offset = Offset - 0.5f;
                            } else if (x > WIDTH / 4 && x < 3 * WIDTH / 4 && y > HEIGHT / 2 && y < HEIGHT) {
                                if (Math.abs(Offset + 0.5f) > 25 || Math.abs(Offset + 0.5f) < 15) {
                                    return;
                                }
                                Offset = Offset + 0.5f;
                            } else if (x < WIDTH / 4) {
                                direction = direction - DEGREE_SPAN;
                            } else if (x > WIDTH / 4) {
                                direction = direction + DEGREE_SPAN;
                            }
                            try {
                                Thread.sleep(100);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start();
                break;
            case MotionEvent.ACTION_UP:
                flag = false;
                break;
        }

        cx = (float) (Math.sin(direction) * Offset);
        cz = (float) (Math.cos(direction) * Offset);

        ux = -cx;
        uy = Math.abs((cx * tx + cz * tz - cx * cx - cz * cz) / (ty - cy));
        uz = -cz;
        for (int i = 0; i < count; i++) {
            fps.get(i).calculateBillboardDirection();
        }
        Collections.sort(this.fps);
        MatrixState.setCamera(cx, cy, cz, tx, ty, tz, ux, uy, uz);
        return true;
    }

    private class SceneRenderer implements Renderer {

        public void onDrawFrame(GL10 gl) {
            GLES30.glClear(GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT);
            MatrixState.pushMatrix();
            for (int i = 0; i < count; i++) {
                MatrixState.pushMatrix();
                fps.get(i).drawSelf(textureIdFire);
                MatrixState.popMatrix();
            }
            MatrixState.popMatrix();
        }

        public void onSurfaceChanged(GL10 gl, int width, int height) {
            // 懂了
            GLES30.glViewport(0, 0, width, height);
            float ratio = (float) width / height;
            MatrixState.setProjectFrustum(-0.3f * ratio, 0.3f * ratio, -1 * 0.3f, 1 * 0.3f, 1, 100);
            MatrixState.setCamera(cx, cy, cz, tx, ty, tz, ux, uy, uz);
            MatrixState.setInitStack();
            MatrixState.setLightLocation(0, 15, 0);
        }

        public void onSurfaceCreated(GL10 gl, EGLConfig config) {    //获取到火堆的总数
            count = ParticleDataConstant.START_COLOR.length;
            //新建一个火堆的数组
            fpfd = new ParticleForDraw[count];
            for (int i = 0; i < count; i++) {
                // 当前的索引
                CURR_INDEX = i;
                // 填充数组，并根据不同的 值
                // TODO 待定
                fpfd[i] = new ParticleForDraw(MySurfaceView.this.getResources(), RADIS[CURR_INDEX]);
                // 根据不同的绘制 创建不同的 火堆系统 设置火堆的 位置z x 火堆
                fps.add(new ParticleSystem(ParticleDataConstant.positionFireXZ[i][0], ParticleDataConstant.positionFireXZ[i][1], fpfd[i], COUNT[i]));
            }

            GLES30.glClearColor(0.6f, 0.3f, 0.0f, 1.0f);

            GLES30.glEnable(GLES30.GL_DEPTH_TEST);

            textureIdFire = initTexture(R.drawable.fire);

            GLES30.glDisable(GLES30.GL_CULL_FACE);
        }
    }

    // 获取纹理的ID
    public int initTexture(int resId) {

        int[] textures = new int[1];
        GLES30.glGenTextures
                (
                        1,
                        textures,
                        0
                );
        int textureId = textures[0];
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE);
        GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE);

        InputStream is = this.getResources().openRawResource(resId);
        Bitmap bitmapTmp;
        try {
            bitmapTmp = BitmapFactory.decodeStream(is);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


        GLUtils.texImage2D
                (
                        GLES30.GL_TEXTURE_2D,
                        0,
                        bitmapTmp,
                        0
                );
        bitmapTmp.recycle();
        return textureId;
    }
}
